//===============================================================================
// Microsoft patterns & practices Enterprise Library Contribution
// Policy Injection Application Block
//===============================================================================

using System;
using System.ComponentModel;
using System.Transactions;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;

namespace EntLibContrib.PolicyInjection.CallHandlers
{
	/// <summary>
	/// An attribute used to apply the <see cref="TransactionScopeCallHandler"/> to the target.
	/// </summary>
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
	public sealed class TransactionScopeCallHandlerAttribute : HandlerAttribute
	{
		#region Fields
		private TransactionScopeOption transactionScopeOption = TransactionScopeOption.Required;
		private TimeSpan timeout = TimeSpan.FromMinutes(1);
		private IsolationLevel isolationLevel = IsolationLevel.Serializable;
		private EnterpriseServicesInteropOption interopOption = EnterpriseServicesInteropOption.None;
		private bool complete = true;
		private static TimeSpanConverter timeSpanConverter = new TimeSpanConverter();
		#endregion

		#region Properties
		/// <summary>
		/// Gets or sets the Transaction Scope Option used by the handler.
		/// </summary>
		/// <value>Transaction Scope Option.</value>
		public TransactionScopeOption TransactionScopeOption
		{
			get { return transactionScopeOption; }
			set { transactionScopeOption = value; }
		}

		/// <summary>
		/// Gets or sets the timeout string.
		/// </summary>
		/// <value>The timeout string.</value>
		public string TimeoutString
		{
			get { return timeSpanConverter.ConvertToString(timeout); }
			set { timeout = (TimeSpan)timeSpanConverter.ConvertFromString(value); }
		}

		/// <summary>
		/// Gets the timeout.
		/// </summary>
		/// <value>The timeout.</value>
		public TimeSpan Timeout
		{
			get { return timeout; }
		}

		/// <summary>
		/// Gets or sets the Isolation Level used by the handler.
		/// </summary>
		/// <value>Scope Option.</value>
		public IsolationLevel IsolationLevel
		{
			get { return isolationLevel; }
			set { isolationLevel = value; }
		}

		/// <summary>
		/// Gets or sets the Interop Option used by the handler.
		/// </summary>
		/// <value>Interop Option.</value>
		public EnterpriseServicesInteropOption InteropOption
		{
			get { return interopOption; }
			set { interopOption = value; }
		}

		/// <summary>
		/// Gets or sets whether the handler will complete the TransactionScope on success.
		/// </summary>
		/// <value><c>true</c> if complete; otherwise, <c>false</c>.</value>
		public bool Complete
		{
			get { return complete; }
			set { complete = value; }
		}
		#endregion

		#region Construction
		/// <summary>
		/// Creates a new TransactionScopeCallHandlerAttribute
		/// </summary>
		public TransactionScopeCallHandlerAttribute()
		{
		}
		#endregion

		#region Public Methods
		/// <summary>
		/// Derived classes implement this method. When called, it
		/// creates a new call handler as specified in the attribute
		/// configuration.
		/// </summary>
		/// <param name="container">The <see cref="T:Microsoft.Practices.Unity.IUnityContainer"/> to use when creating handlers,
		/// if necessary.</param>
		/// <returns>A new call handler object.</returns>
		public override ICallHandler CreateHandler(IUnityContainer container)
		{
			TransactionOptions transactionOptions = new TransactionOptions();
			transactionOptions.Timeout = Timeout;
			transactionOptions.IsolationLevel = IsolationLevel;
			return new TransactionScopeCallHandler(TransactionScopeOption, transactionOptions, InteropOption, Complete, Order);
		}
		#endregion
	}
}
